#include "physics\SimulationCallback.h"
#include "physics/NvidiaPhysX.h"
#include "component/Collider.h"



using namespace Boon;
using namespace Physics;
using namespace physx;



Boon::Physics::SimulationCallback::SimulationCallback( const NvidiaPhysX::MapActorPerGameObject& a, const NvidiaPhysX::MapGOPerActor& go )
	: PxSimulationEventCallback(), m_Actors( a ), m_GameObjects( go )
{

}

void Boon::Physics::SimulationCallback::onConstraintBreak( PxConstraintInfo* constraints, PxU32 count )
{
	
}

void Boon::Physics::SimulationCallback::onWake( PxActor** actors, PxU32 count )
{
	
}

void Boon::Physics::SimulationCallback::onSleep( PxActor** actors, PxU32 count )
{
	
}

void Boon::Physics::SimulationCallback::onContact( const PxContactPairHeader& pairHeader, const PxContactPair* pairs, PxU32 nbPairs )
{
	// callbacks
	for( uint_32 i = 0; i < nbPairs; ++i )
	{
		Collider& c1 = *m_GameObjects.find( NvidiaPhysX::ActorPtrToID( &pairs[i].shapes[0]->getActor() ) )->second.GetCollider();
		Collider& c2 = *m_GameObjects.find( NvidiaPhysX::ActorPtrToID( &pairs[i].shapes[1]->getActor() ) )->second.GetCollider();
	
		if( pairs[i].events == PxPairFlag::eNOTIFY_TOUCH_FOUND )
		{
			c1.OnCollisionEnter( c2 );
			c2.OnCollisionEnter( c1 );
		}
		else if( pairs[i].events == PxPairFlag::eNOTIFY_TOUCH_LOST )
		{
			c1.OnCollisionExit( c2 );
			c2.OnCollisionExit( c1 );
		}
		else if( pairs[i].events == PxPairFlag::eNOTIFY_TOUCH_PERSISTS )
		{
			c1.OnCollisionStay( c2 );
			c2.OnCollisionStay( c1 );
		}
	}
}

void Boon::Physics::SimulationCallback::onTrigger( PxTriggerPair* pairs, PxU32 count )
{
	for( uint_32 i = 0; i < count; ++i )
	{
		Collider& trigger = *m_GameObjects.find( NvidiaPhysX::ActorPtrToID( &pairs[i].triggerShape->getActor() ) )->second.GetCollider();
		Collider& col = *m_GameObjects.find( NvidiaPhysX::ActorPtrToID( &pairs[i].otherShape->getActor() ) )->second.GetCollider();
	
		if( pairs[i].status == PxPairFlag::eNOTIFY_TOUCH_FOUND )
		{
			trigger.OnTriggerEnter( col );
		}
		else if( pairs[i].status == PxPairFlag::eNOTIFY_TOUCH_LOST )
		{
			trigger.OnTriggerExit( col );
		}
		else if( pairs[i].status == PxPairFlag::eNOTIFY_TOUCH_PERSISTS )
		{
			trigger.OnTriggerStay( col );
		}
	}
}

physx::PxFilterFlags Boon::Physics::SimulationFilterCallback::pairFound( PxU32 pairID, PxFilterObjectAttributes attributes0, PxFilterData filterData0, PxActor* a0, PxShape* s0, PxFilterObjectAttributes attributes1, PxFilterData filterData1, PxActor* a1, PxShape* s1, PxPairFlags& pairFlags )
{
	pairFlags = PxPairFlag::eNOTIFY_CONTACT_POINTS | PxPairFlag::eNOTIFY_TOUCH_LOST
		| PxPairFlag::eNOTIFY_TOUCH_PERSISTS | PxPairFlag::eNOTIFY_TOUCH_FOUND
		| PxPairFlag::eRESOLVE_CONTACTS;
	return PxFilterFlags();
}

void Boon::Physics::SimulationFilterCallback::pairLost( PxU32 pairID, PxFilterObjectAttributes attributes0, PxFilterData filterData0, PxFilterObjectAttributes attributes1, PxFilterData filterData1, bool objectDeleted )
{

}

bool Boon::Physics::SimulationFilterCallback::statusChange( PxU32& pairID, PxPairFlags& pairFlags, PxFilterFlags& filterFlags )
{
	pairID = 1;
	filterFlags = PxFilterFlag::eNOTIFY;
	pairFlags = PxPairFlag::eNOTIFY_CONTACT_POINTS | PxPairFlag::eNOTIFY_TOUCH_LOST
		| PxPairFlag::eNOTIFY_TOUCH_PERSISTS | PxPairFlag::eNOTIFY_TOUCH_FOUND
		| PxPairFlag::eRESOLVE_CONTACTS;
	return true;
}

physx::PxFilterFlags Boon::Physics::SimulationFilterCallback::OnCallFilterShader( PxFilterObjectAttributes attributes0, PxFilterData filterData0, PxFilterObjectAttributes attributes1, PxFilterData filterData1, PxPairFlags& pairFlags, const void* constantBlock, PxU32 constantBlockSize )
{
	pairFlags = PxPairFlag::eNOTIFY_CONTACT_POINTS | PxPairFlag::eNOTIFY_TOUCH_LOST
		| PxPairFlag::eNOTIFY_TOUCH_PERSISTS | PxPairFlag::eNOTIFY_TOUCH_FOUND
		| PxPairFlag::eRESOLVE_CONTACTS;
	return PxFilterFlags();
}
